using System;
using System.Collections.Generic;
using NH = NHibernate;
using NHibernate.Criterion;
using NHCfg = NHibernate.Cfg;
using NWrapper.Config;

namespace NWrapper.Repositories.NHibernate
{
	/// <summary>
	/// Repository implementation for NHibernate
	/// (see http://www.hibernate.org/343.html).
	/// </summary>
	public class NHibernateRepository : IRepository, IDisposable
	{
		private RepositorySettings _settings;
		private NH.ISessionFactory _sessionFactory;

		#region IRepository Members
		public void Initialize(RepositorySettings settings)
		{
			if (_sessionFactory != null)
			{
				_sessionFactory.Dispose();
			}

			_settings = settings;
			_sessionFactory = GetSessionFactory(settings);
		}
		#endregion

		#region Properties
		public NH.ISessionFactory SessionFactory
		{
			get
			{
				if (_sessionFactory == null)
					throw new RepositoryException("Repository has not been initialized.");

				return _sessionFactory;
			}
		}
		#endregion

		#region Private Methods
		private NH.ISessionFactory GetSessionFactory(RepositorySettings settings)
		{
			NHCfg.Configuration nhconfig = new NHCfg.Configuration();
			foreach (EntitySettings entitySettings in _settings.Entities)
			{
				nhconfig.AddAssembly(entitySettings.Assembly);
			}

			return nhconfig.BuildSessionFactory();
		}

		private NH.ISession CurrentSession
		{
			get { return this.SessionFactory.OpenSession(); }
		}
		#endregion

		#region IDisposable Members
		public void Dispose()
		{
			if (this.SessionFactory != null)
			{
				this.SessionFactory.Dispose();
			}
		}
		#endregion

		#region IRepository Members
		/// <summary>
		/// Finds the first instance of a given type.
		/// </summary>
		/// <typeparam name="T">The object type.</typeparam>
		/// <returns>An object instance, or null if not found.</returns>
		public T FindFirst<T>()
		{
			throw new NotImplementedException(); 
		}

		/// <summary>
		/// Finds all instances of a given type.
		/// </summary>
		/// <typeparam name="T">The object type.</typeparam>
		/// <returns>An collection of object instance. If no objects are found, an empty collection is returned.</returns>
		public IList<T> FindAll<T>()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Saves an object to the repository.
		/// </summary>
		/// <typeparam name="T">The object type.</typeparam>
		/// <param name="target">The object to save.</param>
		public void Save<T>(T target)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Deletes an object from the repository.
		/// </summary>
		/// <typeparam name="T">The object type.</typeparam>
		/// <param name="target">The object to delete.</param>
		public void Delete<T>(T target)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Deletes all objects of a given type from the repository.
		/// </summary>
		/// <typeparam name="T">The object type.</typeparam>
		public void DeleteAll<T>()
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Reloads an object from the repository.
		/// </summary>
		/// <typeparam name="T">The object type.</typeparam>
		/// <param name="target">The object to reload.</param>
		/// <returns>The reloaded object.</returns>
		public T Resync<T>(T target)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// Gets the total number of records of a given type.
		/// </summary>
		/// <typeparam name="T">The object type.</typeparam>
		/// <returns>The total number of records.</returns>
		public int CountAll<T>()
		{
			throw new NotImplementedException();
		}
		#endregion
	}
}
